#include "clientconnection.h"

// Qt Includes
#include <QThread>
#include <QMetaType>

// Local Includes
#include "clientnetengine.h"
#include "tcpsocket.h"

/////////////////////////////////////////////////////////////////////
// Construction & Destruction
/////////////////////////////////////////////////////////////////////
CClientConnection::CClientConnection(QObject *pParent)
	: QObject(pParent),
	  m_pSocket(NULL),
	  m_pClientNetEngine(NULL),
	  m_pClientThread(NULL)
{

}

CClientConnection::~CClientConnection()
{
	stopClientThread();

	delete m_pClientThread;
	delete m_pClientNetEngine;
	delete m_pSocket;
}
/////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////
// Public Slots
/////////////////////////////////////////////////////////////////////
bool CClientConnection::connectToHost(const QString &strHostAddress, quint16 nPort)
{
	if(strHostAddress.isEmpty() || (nPort == 0))
		return false;

	if(m_pSocket && (m_pSocket->state() == QAbstractSocket::ConnectedState))
		return true;

	if(!m_pSocket)
	{
		m_pSocket = new CTcpSocket;
	}

	// Signals & Slots.
	connect(m_pSocket, SIGNAL(connected()), this, SLOT(onSocketConnected()));

	// TODO - Thomi - can't use QAbstractSocket::SocketError over a queued connection. God knows why...
	//connect(m_pSocket, SIGNAL(error(QAbstractSocket::SocketError)), this,
	//		SLOT(onSocketError()));

	// Asynchronously connect to the server.
	// We will handle the result of this elsewhere.
	m_pSocket->connectToHost(strHostAddress, nPort);

	return true;
}

void CClientConnection::connectToServer(const QString &strUserName, const QString &strPasswordHash)
{
	// We need to invoke the connectToServer method on the CClientNetEngine asynchronously
	// so that we can realise the benefits of using seperate thread.
	QMetaObject::invokeMethod(m_pClientNetEngine, "connectToServer", Qt::QueuedConnection,
			Q_ARG(QString, strUserName), Q_ARG(QString, strPasswordHash));
}
/////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////
// Member Functions
/////////////////////////////////////////////////////////////////////
void CClientConnection::stopClientThread()
{
	if(!m_pClientThread)
		return;

	if(m_pClientThread->isFinished())
		return;

	m_pClientThread->quit();

	if(m_pClientThread->wait(100))
	{
		m_pClientThread->terminate();
	}
}
/////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////
// Private Slots
/////////////////////////////////////////////////////////////////////
void CClientConnection::onSocketConnected()
{
	// We want to stop the thread if it is already running.
	stopClientThread();

	delete m_pClientThread;
	m_pClientThread = new QThread(this);

	delete m_pClientNetEngine;
	m_pClientNetEngine = new CClientNetEngine(m_pSocket);

	m_pClientNetEngine->moveToThread(m_pClientThread);
	m_pClientThread->start();

	emit connected();
}

void CClientConnection::onSocketError()
{
	emit connectFailed(m_pSocket->errorString());
}
/////////////////////////////////////////////////////////////////////
